package cn.zl.web.impl.device;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.zl.GB28181.core.SyncStatus;
import cn.zl.GB28181.storage.IDeviceStorage;
import cn.yunbamboos.exception.AppException;
import cn.yunbamboos.mybatis.conditions.Conditions;
import cn.yunbamboos.rest.service.anno.RestServiceMapping;
import cn.yunbamboos.rest.service.dto.Page;
import cn.yunbamboos.rest.service.dto.out.BaseOutDTO;
import cn.zl.mapper.DeviceChannelMapper;
import cn.zl.mapper.DeviceMapper;
import cn.zl.model.Device;
import cn.zl.web.dto.device.AddDeviceInDTO;
import cn.zl.web.dto.device.AddDeviceOutDTO;
import cn.zl.web.dto.device.DeleteDeviceInDTO;
import cn.zl.web.dto.device.DeleteDeviceOutDTO;
import cn.zl.web.dto.device.QueryDeviceByPageInDTO;
import cn.zl.web.dto.device.QueryDeviceByPageOutDTO;
import cn.zl.web.dto.device.SyncDeviceInDTO;
import cn.zl.web.dto.device.SyncDeviceOutDTO;
import cn.zl.web.dto.device.SyncStatusDeviceInDTO;
import cn.zl.web.dto.device.SyncStatusDeviceOutDTO;
import cn.zl.web.dto.device.UpdateDeviceInDTO;
import cn.zl.web.dto.device.UpdateDeviceOutDTO;
import cn.zl.web.inter.device.IDeviceService;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@Service("DeviceServiceImpl")
public class DeviceServiceImpl implements IDeviceService {

    private static final Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class);

    @Resource
    private DeviceMapper deviceMapper;
    @Resource
    private DeviceChannelMapper deviceChannelMapper;
    @Resource
    private IDeviceStorage deviceStorage;

    @RestServiceMapping(url = "/web/device/queryByPage", name = "条件分页查询设备列表服务", in = QueryDeviceByPageInDTO.class, out = QueryDeviceByPageOutDTO.class)
    @Override
    public BaseOutDTO queryByPage(QueryDeviceByPageInDTO in) {
        // 创建分页对象
        Page<Device> page = new Page<>(in.getPageNo(), in.getPageSize());
        // 添加动态条件
        Conditions where = new Conditions();
        // 查询总数
        int total = deviceMapper.countForPage(page, where);
        // 查询当前页码数据
        List<Device> list = deviceMapper.queryForPage(page, where);
        // 查询设备通道数量
        list.forEach(device -> device.setChannelCount(deviceChannelMapper.countByDeviceId(device.getDeviceId())));
        page.setRows(list).setTotal(total);
        return new QueryDeviceByPageOutDTO(page);
    }

    @RestServiceMapping(url = "/web/device/add", name = "添加新设备服务", in = AddDeviceInDTO.class, out = AddDeviceOutDTO.class)
    @Override
    public BaseOutDTO add(AddDeviceInDTO in) {
        Device device = in.getDevice();
        if (deviceMapper.existDeviceId(device.getDeviceId())) {
            throw AppException.c("国标设备ID({0})已存在", device.getDeviceId());
        }
        String now = LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_PATTERN);
        device.setOnLine(false);
        device.setUpdateTime(now);
        device.setCreateTime(now);
        deviceMapper.insert(device);
        return new AddDeviceOutDTO();
    }

    @RestServiceMapping(url = "/web/device/update", name = "更新设备信息服务", in = UpdateDeviceInDTO.class, out = UpdateDeviceOutDTO.class)
    @Override
    public BaseOutDTO update(UpdateDeviceInDTO in) {
        Device device = in.getDevice();
        deviceMapper.update(device);
        return new UpdateDeviceOutDTO();
    }

    @RestServiceMapping(url = "/web/device/delete", name = "删除设备信息服务", in = DeleteDeviceInDTO.class, out = DeleteDeviceOutDTO.class)
    @Override
    public BaseOutDTO delete(DeleteDeviceInDTO in) {
        in.forEach(id -> {
            deviceMapper.deleteByPrimaryKey(id);
        });
        return new DeleteDeviceOutDTO();
    }

    @RestServiceMapping(url = "/web/device/sync", name = "同步设备信息服务", in = SyncDeviceInDTO.class, out = SyncDeviceOutDTO.class)
    @Override
    public BaseOutDTO sync(SyncDeviceInDTO in) {
        if (logger.isDebugEnabled()) {
            logger.debug("设备通道信息同步API调用，deviceId：{}", in.getDeviceId());
        }
        Device device = this.getDevice(in.getDeviceId());
        if(!device.isOnLine()){
            throw AppException.c("设备 {} 不在线", device.getDeviceName());
        }
        boolean status = deviceStorage.isSyncRunning(device.getDeviceId());
        // 已存在则返回进度
        if (status) {
            SyncStatus channelSyncStatus = deviceStorage.getChannelSyncStatus(device.getDeviceId());
            return new SyncDeviceOutDTO(channelSyncStatus);
        }
        deviceStorage.sync(device);
        return new SyncDeviceOutDTO(null);
    }

    @RestServiceMapping(url = "/web/device/sync-status", name = "同步设备状态信息服务", in = SyncStatusDeviceInDTO.class, out = SyncStatusDeviceOutDTO.class)
    @Override
    public BaseOutDTO syncStatus(SyncStatusDeviceInDTO in) {
        Device device = this.getDevice(in.getDeviceId());
        SyncStatus status = deviceStorage.getChannelSyncStatus(device.getDeviceId());
        if (status == null) {
            throw AppException.c("同步尚未开始");
        }
        return new SyncStatusDeviceOutDTO(status);
    }

    private Device getDevice(String deviceId) {
        Optional<Device> optional = deviceMapper.queryByPrimaryKey(deviceId);
        if (optional.isEmpty()) {
            throw AppException.c("未找到设备");
        }
        return optional.get();
    }

}
